package zpe.controledeacesso.service;


import java.util.ArrayList;
import java.util.List;

import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Service;

import zpe.controledeacesso.model.bean.NivelAcesso;
import zpe.controledeacesso.model.bean.UnidadeTrabalho;
import zpe.controledeacesso.model.bean.Usuario;
import zpe.controledeacesso.security.Acesso;
import zpe.genericcrud.exception.ApplicationException;
import zpe.genericcrud.service.GenericService;

@Service
public class UnidadeTrabalhoService extends GenericService<UnidadeTrabalho> {

	/**
	 * 
	 */
	private static final long serialVersionUID = -8417835209642373837L;

	@SuppressWarnings("unchecked")
	public List<UnidadeTrabalho> getCredes(){
		DetachedCriteria dc = DetachedCriteria.forClass( UnidadeTrabalho.class );
		dc.add( Restrictions.between( "id", 1, 21) )
		.addOrder( Order.asc( "id" ) );
		
		return getDao().getEntityManager().findByCriteria( dc );
	}
	
	@SuppressWarnings("unused")
	public List<UnidadeTrabalho> consultaUnidades( UnidadeTrabalho unidade ){
		DetachedCriteria c = DetachedCriteria.forClass( UnidadeTrabalho.class );
		List<UnidadeTrabalho> lista = new ArrayList<UnidadeTrabalho>();
		if( unidade.getDescricao() != null ){
			lista = findByFilter(UnidadeTrabalho.class, unidade.notEmptyFields(), "descricao" );
		}
		return lista;
	}

	/**
	 * Os níveis de acesso são: <br>
	 * 1 e 2 = Escola; <br>
	 * 3 = Município; <br>
	 * 4 = Crede; <br>
	 * 5 = Seduc; <br>
	 * @param usuario
	 * @param unidade
	 * @param nivelAcesso
	 * @return
	 */
	@SuppressWarnings("unused")
	public List<UnidadeTrabalho> consultaUnidadesByNivelAcesso( Usuario usuario, UnidadeTrabalho unidade ){

		int modulo = Acesso.getModuloSistema();
		NivelAcesso nivelAcesso = usuario.getMaiorNivel( modulo );
		return consultaByNivelEscola(usuario, unidade);
	}
	
	
	/**
	 * Consulta todas as unidades que são subordinadas à unidade e ela mesma.
	 * @param usuario
	 * @param unidade
	 * @return
	 */
	public List<UnidadeTrabalho> consultaByNivelEscola( Usuario usuario, UnidadeTrabalho unidade ){
		DetachedCriteria c = DetachedCriteria.forClass( UnidadeTrabalho.class );
		
		c.add(Restrictions.eq("ativo", "S"));
		return consulta(c, unidade);
	}
	
	/**
	 * Consulta todas as escolas municipais e municipais conveniadas do município.
	 * @param usuario
	 * @param unidade
	 * @return
	 */
	public List<UnidadeTrabalho> consultaByNivelMunicipio( Usuario usuario, UnidadeTrabalho unidade ){
		DetachedCriteria c = DetachedCriteria.forClass( UnidadeTrabalho.class );
		
		c.createAlias( "tipo", "tipo");
		c.add( Restrictions.in( "tipo.id", new Integer[]{5, 11} ) );
		c.add(Restrictions.eq("ativo", "S"));
		return consulta(c, unidade);
	}
	
	
	/**
	 * Vê todas as unidades
	 * @param usuario
	 * @param unidade
	 * @return
	 */
	public List<UnidadeTrabalho> consultaByNivelSede( Usuario usuario, UnidadeTrabalho unidade ){
		DetachedCriteria c = DetachedCriteria.forClass( UnidadeTrabalho.class );
		c.createAlias( "tipo", "tipo");
		c.add( Restrictions.in( "tipo.id", new Integer[]{1, 2, 3, 5, 6, 11, 15} ) );
		c.add(Restrictions.eq("ativo", "S"));
		return consulta(c, unidade);
	}
	
	@SuppressWarnings("unchecked")
	private List<UnidadeTrabalho> consulta( DetachedCriteria c, UnidadeTrabalho unidade ){
		List<UnidadeTrabalho> lista = new ArrayList<UnidadeTrabalho>();
		c.add( Restrictions.eq( "ativo", 'S' ) );
		 if( unidade.getDescricao() != null ){
			c.add( Restrictions.ilike( "descricao", unidade.getDescricao(), MatchMode.ANYWHERE ) )
			.addOrder( Order.asc( "descricao" ) );
		}
		
		lista = getDao().getEntityManager().findByCriteria( c );
		
		if( lista.isEmpty() ){
			throw new ApplicationException( "Unidade não encontrada ou nível de acesso insuficiente." );
		}
		return lista;
	}
	
	
	
}